Package nz.ac.massey.softwarec.group3.game

Source Code of nz.ac.massey.softwarec.group3.game.Game

/*
New Scotland Yard is an online multiplayer adaptation
of the boardgame  "Scotland Yard". Copyright (C) 2011 
Massey University Software C Group 3

This program is free software: you can redistribute it
and/or modify it under the terms of the GNU General
Public License as published by the Free Software
Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General
Public License along with this program.  If not, see
<http://www.gnu.org/licenses/>.
*/

package nz.ac.massey.softwarec.group3.game;

import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import nz.ac.massey.softwarec.group3.game.map.Map;
import nz.ac.massey.softwarec.group3.game.map.MapStation;
import nz.ac.massey.softwarec.group3.reverseAJAX.ReverseAJAXCall;
import tokbox.com.opentok.api.*;
import tokbox.com.opentok.api.constants.RoleConstants;
import tokbox.com.opentok.exception.OpenTokException;

/**
* Game - Class for objects that describe a game, and performs all the game operations.
* @version 1.0 Release
* @since 1.0
* @authors Natalie Eustace | Wanting Huang | Paul Smith | Craig Spence
*/
public class Game implements GameInterface {
   
    private final transient String creatorEmail;
    private transient String creatorName, openTokSessionId;
    private transient List<Player> players = new ArrayList<Player>();
    private transient Map map;
    private transient MrX mrX;
    private final transient List<Move> mrXMoves = new ArrayList<Move>();
    private transient boolean hasMrX = false, playing = false, finished = false, doubleMove = false;
    private final transient int gameID;
    private transient int whosTurn;
   
    /**
     * Game constructor to make a new game object.
     * @param String creatorEmail - The name of the user creating the game.
     * @param int gameID - the ID number of this game.
     */
    public Game(final String creatorEmail, final int gameID) {
        this.creatorEmail = creatorEmail;
        this.gameID = gameID;
        Player player;
        player = decidePlayerType();
        player.setPlayerEmail(creatorEmail);
        players.add(player);
    }   
   
    /**
     * Getter for creatorEmail.
     * @return String creatorEmail - The name of the user who created the game.
     */
    @Override
    public String getCreatorEmail() {
        return creatorEmail;
    }
   
    /**
     * Getter for Game creator's name
     * @return String creatorName - The full name of the game's creator.
     */
    public String getCreatorName() {
        return creatorName;
    }
   
    /**
     * Setter for game creator's name
     * @param creatorName
     */
    public void setCreatorName(final String creatorName) {
        this.creatorName = creatorName;
    }
   
    /**
     * Getter for game map
     * @return map
     */
    @Override
    public Map getMap() {
        return map;
    }
   
    /**
     * Setter for map
     * @param map
     */
    @Override
    public void setMap(final Map map) {
        this.map = map;
    }
   
    /**
     * Getter for game's id
     * @return gameID
     */
    @Override
    public int getGameID() {
        return gameID;
    }
   
    /**
     * Getter for which player for the current turn
     * @return whosTurn
     */
    @Override
    public int getWhosTurn() {
        return whosTurn;
    }
   
    /**
     * Getter for Mr X's moves
     * @return mrXMoves
     */
    public List<Move> getMrXMoves() {
        return mrXMoves;
    }
   
    /**
     * Getter for the Player objects.
     * @return ArrayList<Player> players - The ArrayList of players who are associated with the game.
     */
    @Override
    public List<Player> getPlayers() {
        return players;
    }
   
    /**
     * Method to check if playing
     * @return true if yes else false
     */
    @Override
    public boolean isPlaying() {
        return this.playing;
    }
   
    /**
     * Setter to check if playing
     * @param playing
     */
    @Override
    public void setPlaying(final boolean playing) {
        this.playing = playing;
    }
   
    /**
     * Setter to set which player is next to take a turn
     * @param playerIndex
     */
    @Override
    public void setWhosTurn(final int playerIndex) {
        this.whosTurn = playerIndex;
    }
   
    /**
     * Setter for video chat id
     */
    public void setTokSessionId() {
        final OpenTokSDK sdk = new OpenTokSDK(API_Config.API_KEY,API_Config.API_SECRET);
        try {
            final String newSessionId = sdk.create_session().session_id;
            this.openTokSessionId = newSessionId;
        } catch (OpenTokException ex) {
            System.err.print(ex);
        }  
    }
   
    //********************************************************//
    //Setting up the game to handle video and voice chat
    //using the OpenTok library.
   
    /**
     * Getter for video chat id
     * @return
     */
    public String getOpenTokSessionId() {
        return openTokSessionId;
    }
   
    /**
     * Getter for video chat token
     * @return
     */
    public String getOpenTokIdToken() {
        final OpenTokSDK sdk = new OpenTokSDK(API_Config.API_KEY, API_Config.API_SECRET);
        try {
            return sdk.generate_token(openTokSessionId, RoleConstants.PUBLISHER);
        } catch (OpenTokException ex) {
            System.err.print(ex);
        }
        return null;
    }
   
    /**
     * Getter for video chat API key
     * @return
     */
    public int getOpenTokAPIKey() {
        return API_Config.API_KEY;
    }
    //********************************************************//
   
   
   
    /**
     * Getter to see if game is finished.
     * @return
     */
    public boolean isFinished() {
        return finished;
    }
   
    /**
     * Getter to get a particular player
     * @param email
     * @return player
     */
    @Override
    public Player getPlayer(final String email) {
        for (Player player : players) {
            if (player.getPlayerEmail().equals(email)) {
                return player;
            }
        }
        return null;
    }
   
    /**
     * A method to check if a given user is currently in the game.
     * @param String userName - The name of the user who we are checking.
     * @return boolean - Whether or not a user is in this game.
     */
    @Override
    public boolean checkIfUserIsInGameAlready(final String userEmail) {
        final List<String> currentEmails = getCurrentPlayerNames();
        for (String email : currentEmails) {
            if (email.equals(userEmail)) {
                //TODO ALREADY IN GAME
                return true;
            }
        }
        return false;
    }
   
    /**
     * Getter for the names of all the players.
     * @return ArrayList<String> currentPlayers - The ArrayList of the names of this games players.
     */
    private List<String> getCurrentPlayerNames() {
        final ArrayList<String> currentPlayers = new ArrayList<String>();
        for (Player player : players) {
            currentPlayers.add(player.getPlayerEmail());
        }
        return currentPlayers;
    }
   
    /**
     * Method that checks if a user is in a game, and if not, creates a new
     * Player and adds it to the game.
     * @param String userName - The username of the user to be added to the game.
     */
    @Override
    public void addUserToGame(final String email) {
        if (!checkIfUserIsInGameAlready(email)) {
            final Player player = decidePlayerType();
            if (player == null) {
                gameIsFull();
            }
            else {
                player.setPlayerEmail(email);
                players.add(player);
            }
        }
    }
   
    /**
     * method to remove a particular user from the game
     * @param email
     * @return true if player removed, false otherwise
     */
    @Override
    public boolean removeUserFromGame(final String email) {
        if (checkIfUserIsInGameAlready(email)) {
            for (Player player : players) {
                if (player.getPlayerEmail().equals(email)) {
                    players.remove(player);
                    return true;
                }
            }
        }
        return false;
    }
       
    /**
     * Method that determines what sort of Player object will be created,
     * with type determined randomly (or if there is not a Mr. X when the last
     * player is added, the last Player is definitely a Mr. X).
     * @return Player - the newly created Player object.
     */
    private Player decidePlayerType() {
        if (players.size() < 6) {
            final double random = Math.random() * 6;
            if (!hasMrX && (random > 5 || players.size() == 5)) {
                hasMrX = true;
                mrX = new MrX();
                return mrX;
            }
        }
        return new Detective();
    }

    /**
     * Placeholder to check if game is full
     */
    private void gameIsFull() {
        throw new UnsupportedOperationException("Not yet implemented");
    }
   
    /**
     * Method to find out who is Mr X
     * @return mrX
     */
    public MrX getMrX() {
        return mrX;
    }
   
    /**
     * Method to start the game
     */
    @Override
    public void startGame() {
        assignMrX();
        setMrXToFirst();
        assignExtraDetectives();
        assignStartPositions();
        handOutMrXTokens();
        setWhosTurn(0);
    }
   
    /**
     * Method to randomly assign Mr X to a player
     */
    private void assignMrX() {
        if (!hasMrX) {
            final Random random = new Random();
            final int nextRandom = random.nextInt(players.size());
            mrX = new MrX();
            mrX.setPlayerEmail(players.get(nextRandom).getPlayerEmail());
            players.set(nextRandom, mrX);
        }
    }
   
    /**
     * Method to ensure MrX is first player to move
     */
    private void setMrXToFirst() {
        Collections.sort(players);
    }
   
    /**
     * Method to give players control of more detectives
     * if number of players is between and including 3 and 5
     */
    private void assignExtraDetectives() {
        int detectivePlayerIndex = 1;
        int numberOfDetectivePlayers = players.size() - 1;
        while (players.size() < 6) {
            Detective detective = new Detective();
            detective.setPlayerEmail(players.get(detectivePlayerIndex).getPlayerEmail());
            players.add(detective);
            if (detectivePlayerIndex < numberOfDetectivePlayers) {
                detectivePlayerIndex++;
            }
            else {
                detectivePlayerIndex = 1;
            }
        }
        List<String> playerEmails = new ArrayList<String>();
        for (Player player : players){
            if (!playerEmails.contains(player.getPlayerEmail())) {
                playerEmails.add(player.getPlayerEmail());
            }
        }
        List<Player> orderedListOfPlayers = new ArrayList<Player>();
        for (String email: playerEmails) {
            List<Player> playersForThisEmail = new ArrayList<Player>();
            for (Player player: players) {
                if (player.getPlayerEmail().equals(email)) {
                    playersForThisEmail.add(player);
                }
            }
            orderedListOfPlayers.addAll(playersForThisEmail);
        }
        players = orderedListOfPlayers;
    }
   
    /**
     * Method to randomly assign players starting positions
     */
    private void assignStartPositions() {
        final List<Integer> startPositions = new ArrayList<Integer>();
        final Random random = new Random();
        while (startPositions.size() < 6) {
            final int nextRandom = random.nextInt(map.getNumberOfMapStations());
            if (!startPositions.contains(nextRandom)) {
                startPositions.add(nextRandom);
            }
        }
        for (int i = 0; i < players.size(); i++) {
            players.get(i).setCurrentLocation(map.getMapStation(startPositions.get(i)));
        }
    }
   
    /**
     * Method to set number of jetpack(mrX black) tickets for MrX
     */
    private void handOutMrXTokens() {
        mrX.giveMrXTokens(players.size() - 1);
    }
   
    /**
     * Method to cause a player to take a turn
     * @param value
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public void playerTakesTurn(final String value) throws ParserConfigurationException, SAXException, IOException{
        final Move move = createMove(value);
        final MapStation mapNode = map.getMapStation(move.getDestinationNode());
        if (!mrXLose(move)) {
            if ("TAXI".equals(move.getTicketType())) {
                players.get(whosTurn).useTaxiToken();
                players.get(whosTurn).setCurrentLocation(mapNode);
                if (!players.get(whosTurn).isMrX()) {
                    mrX.giveTravelToken(0);
                }
            } else if ("BUS".equals(move.getTicketType())) {
                players.get(whosTurn).useBusToken();
                players.get(whosTurn).setCurrentLocation(mapNode);
                if (!players.get(whosTurn).isMrX()) {
                    mrX.giveTravelToken(1);
                }
            } else if ("UNDERGROUND".equals(move.getTicketType())) {
                players.get(whosTurn).useUndergroundToken();
                players.get(whosTurn).setCurrentLocation(mapNode);
                if (!players.get(whosTurn).isMrX()) {
                    mrX.giveTravelToken(2);
                }
            } else if ("MRX".equals(move.getTicketType())) {
                mrX.useMrXToken();
                mrX.setCurrentLocation(mapNode);
            }
            if (players.get(whosTurn).isMrX()) {
                mrX.move();
                mrXMoves.add(move);
                if (mrXMoves.isEmpty() || mrXMoves.size() == 5 || mrXMoves.size() == 10 || mrXMoves.size() == 15 || mrXMoves.size() == 21) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X will show himself in 3 turns!");
                }
                if (mrXMoves.size() == 1 || mrXMoves.size() == 6 || mrXMoves.size() == 11 || mrXMoves.size() == 16  || mrXMoves.size() == 22) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X will show himself in 2 turns!");
                }
                if (mrXMoves.size() == 2 || mrXMoves.size() == 7 || mrXMoves.size() == 12 || mrXMoves.size() == 17  || mrXMoves.size() == 23) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X will show himself in 1 turn!");
                }
                if (mrXMoves.size() == 3 || mrXMoves.size() == 8 || mrXMoves.size() == 13 || mrXMoves.size() == 18 || mrXMoves.size() == 24) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X has been spotted!");
                }
                if (mrXMoves.size() == 4 || mrXMoves.size() == 9 || mrXMoves.size() == 14  || mrXMoves.size() == 20) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X will show himself in 4 turns!");
                }
                if (mrXMoves.size() == 19) {
                    final ReverseAJAXCall call = new ReverseAJAXCall();
                    call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "slideOutAlert", "Mr. X will show himself in 5 turns!");
                }
            }
            determineWhosTurnItIsNext();
        }
    }
   
    /**
     * Method to use to detect if MrX has lost
     * @param move
     * @return
     */
    private boolean mrXLose(final Move move) {
        if (!players.get(whosTurn).isMrX()) {
            if (map.getMapStation(move.getDestinationNode()) == mrX.getCurrentLocation()) {
                broadcastGameEnded("players");
                return true;
            }
        }
        if (!getMrX().getCanMove()) {
            return true;
        }
        return false;
    }
   
    /**
     * Method to check if players have lost
     */
    public void checkPlayersLose() {
        boolean playersLose = true;
        for (Player player : players) {
            if (!player.isMrX()) {
                if (player.getCanMove()) {
                    playersLose = false;
                }
            }
        }
        if (playersLose) {
            broadcastGameEnded("mrX");
        }
    }

    /**
     * Method to determine whos turn it is for the next move
     */
    public void determineWhosTurnItIsNext() {
        if (!doubleMove) {
            int nextTurn = whosTurn;
            if (nextTurn == players.size() - 1) {
                nextTurn = -1;
            }
            for (int i = nextTurn + 1; i < players.size(); i++) {
                if (players.get(i).getInGame()) {
                    whosTurn = i;
                    i = players.size();
                }
            }
            tellGameToUpdate(null);
        }
        else {
            mrX.useDoubleMoveToken();
            doubleMove = false;
            tellGameToUpdate("DOUBLE");
        }
    }

    /**
     * Method to use reverse ajax to update
     * @param updateParams
     */
    private void tellGameToUpdate(final String updateParams) {
        final ReverseAJAXCall call = new ReverseAJAXCall();
        call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "updateGame", updateParams);
    }
   
    /**
     * Method to broadcast to all players that the game has ended
     * @param winner
     */
    private void broadcastGameEnded(final String winner) {
        finished = true;
        final ReverseAJAXCall call = new ReverseAJAXCall();
        call.createFilteredFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/ingame.jsp", "Game", creatorEmail, "endGame", winner);
    }

   
    /**
     * Method to create a move
     * @param XMLstring
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    private Move createMove(final String XMLstring) throws ParserConfigurationException, SAXException, IOException{
        String moveType = "";
        int originNode = 0;
        int destinationNode = 0;

        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
        final InputSource inputSource = new InputSource();
        inputSource.setCharacterStream(new StringReader(XMLstring));
        final Document document = documentBuilder.parse(inputSource);

        //Get move type
        final NodeList XMLmoveTypeList = document.getElementsByTagName("movetype");
        final Element moveTypeElement = (Element) XMLmoveTypeList.item(0);
        moveType = moveTypeElement.getAttribute("type");

        //Get origin Node
        final NodeList XMLoriginList = document.getElementsByTagName("origin");
        final Element originElement = (Element) XMLoriginList.item(0);
        originNode = Integer.parseInt(originElement.getAttribute("stationid"));

        //Get destination Node
        final NodeList XMLdestinationList = document.getElementsByTagName("destination");
        final Element destinationElement = (Element) XMLdestinationList.item(0);
        destinationNode = Integer.parseInt(destinationElement.getAttribute("stationid"));

        return new Move(moveType, originNode, destinationNode);
    }

    /**
     * Method to tell the lobby that there is a game
     */
    public void tellLobby() {
        final ReverseAJAXCall call = new ReverseAJAXCall();
        call.createFunctionCall("/Software_Engineering_C/Resources/JavaServerPages/lobby.jsp", "addGame", null);
    }

   

    /**
     * Method for double move
     */
    public void startDoubleTurn() {
        doubleMove = true;
    }
   
    /**
     * Method to end double move
     */
    public void cancelDoubleTurn() {
        doubleMove = false;
    }

    /**
     * Method to handle if a player has no tickets to
     * move off current station
     */
    public void strandedPlayer() {
        determineWhosTurnItIsNext();
    }

    /**
     * Method to check if game has ended
     */
    public void checkEnd() {
        if (!players.get(0).getInGame()) {
            broadcastGameEnded("players");
        }
        if (players.get(0).getInGame() && !players.get(1).getInGame() && !players.get(2).getInGame() && !players.get(3).getInGame() && !players.get(4).getInGame() && !players.get(5).getInGame()) {
            broadcastGameEnded("mrX");
        }  
    }
}
TOP

Related Classes of nz.ac.massey.softwarec.group3.game.Game

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.